package cn.tedu.straw.portal.service.impl;

import cn.tedu.straw.portal.Schedule.CacheSchedule;
import cn.tedu.straw.portal.mapper.ClassInfoMapper;
import cn.tedu.straw.portal.mapper.PermissionMapper;
import cn.tedu.straw.portal.mapper.UserMapper;
import cn.tedu.straw.portal.mapper.UserRoleMapper;
import cn.tedu.straw.commons.model.ClassInfo;
import cn.tedu.straw.commons.model.Permission;
import cn.tedu.straw.commons.model.User;
import cn.tedu.straw.commons.model.UserRole;

import cn.tedu.straw.portal.service.IUserService;
import cn.tedu.straw.portal.service.ex.ClassDisabledException;
import cn.tedu.straw.portal.service.ex.InsertException;
import cn.tedu.straw.portal.service.ex.InviteCodeException;
import cn.tedu.straw.portal.service.ex.PhoneDuplicateException;
import cn.tedu.straw.commons.vo.TagVO;
import cn.tedu.straw.commons.vo.TeacherVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.xml.internal.bind.v2.TODO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author shkstart
 * @create 2020-07-15 15:29
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements IUserService {
    @Autowired
    private ClassInfoMapper classInfoMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    private PasswordEncoder passwordEncoder=new BCryptPasswordEncoder();



    @Autowired
PermissionMapper permissionMapper;


    @Override
    @Transactional
    public void registerStudent(User user, String inviteCode) {
        QueryWrapper<ClassInfo> classQueryWrapper = new QueryWrapper<>();
        classQueryWrapper.eq("invite_code", inviteCode);
        ClassInfo classInfo = classInfoMapper.selectOne(classQueryWrapper);

        if (classInfo == null) {
            throw new InviteCodeException("注册失败!邀请码异常错误1");
        }

        if(classInfo.getEnabled()==0){
            throw new ClassDisabledException("注册失败!班级已经被禁用!");
        }

        String phone = user.getPhone();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("phone", user.getPhone());
        User result = userMapper.selectOne(userQueryWrapper);
        if (result != null) {
            throw new PhoneDuplicateException("注册失败!手机号已经被注册!");
        }
        //将手机号作为用户名
        user.setUsername(user.getPhone());
        String rawpassword = user.getPassword();
        String encodePassword = encode(rawpassword);
        user.setPassword(encodePassword);
        user.setClassId(classInfo.getId());
        user.setCreatedTime(LocalDateTime.now());
        user.setEnabled(1);
        user.setLocked(0);
        user.setType(0);

        int rows = userMapper.insert(user);
        if(rows!=1){
            throw new InsertException("注册失败!服务器忙,请稍后再试!");
        }

        //向"用户角色表"中插入数据,为当前学生账号分配角色
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(2);//学生角色的id固定为2,具体可见user_role数据表
         rows = userRoleMapper.insert(userRole);
         //判断返回值(受影响的行数)是否不为1
        if (rows != 1){
            //是:受影响的行数不是1,则插入的数据失败,抛出InsertException
            throw new InsertException("注册失败!服务器忙,请稍后再次尝试!");
        }
    }




    private List<TeacherVO> teachers=new CopyOnWriteArrayList<>();
    @Override
    public List<TeacherVO> getTeachers() {
        if(teachers.isEmpty()){
            synchronized (CacheSchedule.lock_CANCHE){
                if (teachers.isEmpty()){
                    teachers.addAll(userMapper.findTeachers());
                }
            }
        }
        return teachers;
    }

    @Override
    public List<TeacherVO> getCachedTeachers() {
        return teachers;
    }


    /**
     * 执行秘密加密
     *
     * @param rawPassword 原密码
     * @return 根据原密码执行加密得到的密文
     */
    private String encode(String rawPassword){
        String encodePassword = passwordEncoder.encode(rawPassword);
        encodePassword="{bcrypt}"+encodePassword;
        return encodePassword;
    }

}
